﻿using System;
using System.Collections.Generic;
using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;
using Rhino.Mocks;
using SimpleServiceBus.EndpointManagement.Server.Wcf;
using SimpleServiceBus.EndpointManagement.Wcf.Contracts.Data;
using SimpleServiceBus.Messages.Management.Monitoring;
using SimpleServiceBus.Persistence.Domain.Management.Entities;
using SimpleServiceBus.Persistence.Domain.Management.Repositories;

namespace SimpleServiceBus.Tests.Server.Wcf
{
    [TestFixture]
    public class EndpointManagementWebServiceTestFixture
    {
        [Test]
        public void GetEndpointShouldReturnEndpointContract()
        {
            //Given
            var epRepo = MockRepository.GenerateStub<IManagedEndpointRepository>();
            var service = new EndpointManagementWebService(epRepo, null, null, new AutoMapperContractMapper());

            epRepo.Stub(ep => ep.GetByEndpointId("123")).Return(new ManagedEndpoint
                                                                    {Id = 1, EndpointID = "Hello", LastStatusUpdate = DateTime.Today, StatusNote = "A Note"});
            
            //When
            ManagedEndpointContract result = service.GetEndpoint("123");

            //Then
            Assert.That(result.EndpointID, Is.EqualTo("Hello"));
            Assert.That(result.LastStatusUpdate,Is.EqualTo(DateTime.Today));
            Assert.That(result.StatusNote,Is.EqualTo("A Note"));
        }

        [Test]
        public void GetAllEndpointsShouldFetchAndMapMultipleEndpoints()
        {
            //Given
            var epRepo = MockRepository.GenerateStub<IManagedEndpointRepository>();
            epRepo.Stub(epr => epr.FindAll()).Return(new List<ManagedEndpoint>
                                                         {
                                                             new ManagedEndpoint {Id = 1, Name = "Name1"},
                                                             new ManagedEndpoint {Id = 2, Name = "Name2"}
                                                         });

            var service = new EndpointManagementWebService(epRepo, null, null, new AutoMapperContractMapper());

            //When
            List<ManagedEndpointContract> results = service.GetAllEndpoints();

            //Then
            Assert.That(results.Count, Is.EqualTo(2));
            Assert.That(results[0].Name, Is.EqualTo("Name1"));
            Assert.That(results[1].Name, Is.EqualTo("Name2"));
        }

        [Test]
        public void GetEndpointErrorShouldFetchAndConvertErrorContract()
        {
            //Given
            var errorRepo = MockRepository.GenerateStub<IEndpointErrorRepository>();
            errorRepo.Stub(er => er.Get(1)).Return(new EndpointError
                                                       {
                                                           ErrorMessage = "Uh Oh",
                                                           FailedMessageID = "123",
                                                           Id = 1,
                                                           Timestamp = DateTime.Today,
                                                           ManagedEndpoint =
                                                               new ManagedEndpoint {Id = 1, EndpointID = "Endpoint"}
                                                       });

            var service = new EndpointManagementWebService(null, errorRepo, null, new AutoMapperContractMapper());

            //When
            EndpointErrorContract result = service.GetEndpointError(1.ToString());

            //Then
            Assert.That(result.ErrorMessage,Is.EqualTo("Uh Oh"));
            Assert.That(result.FailedMessageID, Is.EqualTo("123"));
            Assert.That(result.Id, Is.EqualTo(1));
            Assert.That(result.Timestamp, Is.EqualTo(DateTime.Today));
            Assert.IsNotNull(result.ManagedEndpoint);
            Assert.That(result.ManagedEndpoint.EndpointID, Is.EqualTo("Endpoint"));
            
        }

        [Test]
        public void GetEndpointErrorsByEndpointIdShouldRequestErrorsForProvidedEndpointId()
        {
            //Given
            var epRepo = MockRepository.GenerateStub<IManagedEndpointRepository>();
            var errorRepo = MockRepository.GenerateStub<IEndpointErrorRepository>();

            var endpoint = new ManagedEndpoint {Id = 1, EndpointID = "ep1"};
            epRepo.Stub(epr => epr.GetByEndpointId("ep1")).Return(endpoint);
            errorRepo.Stub(er => er.FindByEndpoint(endpoint, 25, null, null)).Return(new List<EndpointError>
                                                                                                   {
                                                                                                       new EndpointError
                                                                                                           {Id = 1,
                                                                                                            ErrorMessage="aww crap!",
                                                                                                            ManagedEndpoint=endpoint
                                                                                                           }
                                                                                                   });

            var service = new EndpointManagementWebService(epRepo, errorRepo, null, new AutoMapperContractMapper());

            //When
            IList<EndpointErrorContract> results = service.GetEndpointErrorsByEndpointId("ep1", 25);

            //Then
            Assert.That(results.Count, Is.EqualTo(1));
            Assert.That(results[0].ErrorMessage, Is.EqualTo("aww crap!"));
            Assert.That(results[0].ManagedEndpoint, Is.Not.Null);
            Assert.That(results[0].ManagedEndpoint.EndpointID, Is.EqualTo("ep1"));
        }

        [Test]
        public void GetEndpointErrorsShouldFetchAndMapErrors()
        {
            //Given
            var errorRepo = MockRepository.GenerateStub<IEndpointErrorRepository>();
            errorRepo.Stub(er => er.FindAll(1, null, null)).Return(new List<EndpointError>
                                                                               {
                                                                                   new EndpointError
                                                                                       {Id = 1,
                                                                                        ErrorMessage="aww crap!",
                                                                                        ManagedEndpoint=null
                                                                                       }
                                                                               });

            var service = new EndpointManagementWebService(null, errorRepo, null, new AutoMapperContractMapper());
            
            //When
            IList<EndpointErrorContract> results = service.GetEndpointErrors(1);

            //Then
            Assert.That(results.Count, Is.EqualTo(1));
            Assert.That(results[0].ErrorMessage, Is.EqualTo("aww crap!"));
        }

        [Test]
        public void GetPerfSummariesByEndpointIdShouldRequestSummariesForProvidedEndpointId()
        {
            //Given
            var epRepo = MockRepository.GenerateStub<IManagedEndpointRepository>();
            var perfRepo = MockRepository.GenerateStub<IEndpointPerformanceSummaryRepository>();

            var endpoint = new ManagedEndpoint { Id = 1, EndpointID = "ep1" };
            epRepo.Stub(epr => epr.GetByEndpointId("ep1")).Return(endpoint);
            perfRepo.Stub(er => er.FindByEndpoint(endpoint, 25, null, null)).Return(new List<EndpointPerformanceSummary>
                                                                                                   {
                                                                                                       new EndpointPerformanceSummary
                                                                                                           {Id = 1,
                                                                                                            Metric = new EndpointMetricType{CanAggregate = true,DataType=MeasurementDataType.Numeric,Id=1,Name="MetricType",UnitOfMeasurement="gb"},
                                                                                                            Average=100.0,
                                                                                                            SamplePeriodStartTime=DateTime.Today,
                                                                                                            ManagedEndpoint=endpoint
                                                                                                           }
                                                                                                   });

            var service = new EndpointManagementWebService(epRepo, null, perfRepo, new AutoMapperContractMapper());

            //When
            IList<EndpointPerformanceSummaryContract> results = service.GetEndpointPerformanceSummaries("ep1", 25);

            //Then
            Assert.That(results.Count, Is.EqualTo(1));
            Assert.That(results[0].Average,Is.EqualTo(100.0));
            Assert.That(results[0].SamplePeriodStartTime, Is.EqualTo(DateTime.Today));
            Assert.That(results[0].ManagedEndpoint.EndpointID, Is.EqualTo("ep1"));
            Assert.That(results[0].Metric.UnitOfMeasurement, Is.EqualTo("gb"));
            Assert.That(results[0].Metric.DataType, Is.EqualTo("Numeric"));
        }
    }
}
